﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using XMLGener.Interfaces;
using XMLGener.Data;

namespace XBasicModules
{
    /// <summary>
    /// CVS genertator is data generator that reads specific column from CSV file.
    /// </summary>
    public class CSVGenerator : ModuleBase, XMLGenerModuleInterface
    {
        private Random rnd = new Random();
        private string sourceFile = "";
        private int column = 0;
        private bool skip = false;
        private bool trim = false;
        private int currentIndex = 0;
        #region XMLGenerModuleInterface Members

        /// <summary>
        /// Return next random number;
        /// </summary>
        /// <returns></returns>
        public virtual string generate()
        {
            if(cachedColumns==null || cachedColumns.Count<1)
                return "";
            if (currentIndex >= cachedColumns.Count)
                currentIndex = 0;
            return cachedColumns[currentIndex++];

        }

        /// <summary>
        /// Retrurn definitnion of this module
        /// </summary>
        /// <returns>xml data</returns>
        public virtual string getDefinition()
        {
            return
              "<function>" +
              "   <name>CSV reader</name>" +
              "   <id>csvreader</id>" +
              "   <type>string</type>" +
              "   <attributes>" +
              "      <attribute>" +
              "         <name>Source file</name>" +
              "         <id>source</id>" +
              "         <type>file</type>" +
              "      </attribute>" +
              "      <attribute>" +
              "         <name>Column number</name>" +
              "         <id>column</id>" +
              "         <type>number</type>" +
              "      </attribute>" +
              "      <attribute>" +
              "         <name>Column indexing starts with 0 (0=first column).</name>" +
              "         <id>i0</id>" +
              "         <type>info</type>" +
              "      </attribute>" +
              "      <attribute>" +
              "         <name>Skip header</name>" +
              "         <id>skip</id>" +
              "         <type>bool</type>" +
              "      </attribute>" +
              "      <attribute>" +
              "         <name>If &quot;Skip header&quot; is checked, reading will start from 2nd line.</name>" +
              "         <id>i1</id>" +
              "         <type>info</type>" +
              "      </attribute>" +
              "      <attribute>" +
              "         <name>Trim data</name>" +
              "         <id>trim</id>" +
              "         <type>bool</type>" +
              "      </attribute>" +
              "   </attributes>" +
              "</function>";
        }

        private List<string> cachedColumns = null;
        /// <summary>
        /// Set attributes for this module before generating.
        /// </summary>
        /// <param name="xmlParams"></param>
        /// <param name="parentDocument"></param>
        public virtual void setParameters(string xmlParams, XMLGenerDocument parentDocument)
        {
            if (!this.checkSettingsElement(xmlParams, parentDocument))
                return;
            this.sourceFile = this.getParam("source");
            this.column = Convert.ToInt32(this.getParam("column"));
            this.skip = (this.getParam("skip") == "1");
            this.trim = (this.getParam("trim") == "1");
            currentIndex = 0;

            cachedColumns = new List<string>();
            string line = null;
            FileInfo fi = new FileInfo(sourceFile);
            if (!fi.Exists)
                return;
            StringBuilder charStack = new StringBuilder();
            int i = 0;
            int currentColumn = 0;
            char setSeparator = '\0';
            bool readNextLine = false;
            string newItem;
            using (TextReader streamReader = new StreamReader(sourceFile))
            {
                
                while ((line = streamReader.ReadLine()) != null)
                {
                    i = 0;
                    charStack.Length=0;
                    readNextLine = false;
                    while (i < line.Length && !readNextLine)
                    {
                        if (line[i]==setSeparator)
                        {
                            setSeparator='\0';
                        }else
                        switch (line[i])
                        {
                            case ';':
                                if (setSeparator == '\0')
                                {
                                    if (currentColumn == this.column)
                                    {
                                        newItem = charStack.ToString();
                                        if(trim)
                                            newItem = newItem.Trim();
                                        if (!string.IsNullOrEmpty(newItem))
                                            cachedColumns.Add(newItem);
                                        readNextLine = true;
                                        break;
                                    }
                                    currentColumn++;
                                }
                                break;
                            case '"':
                            case '\'':
                                setSeparator = line[i];
                                break;
                            default:
                                if (currentColumn == this.column)
                                    charStack.Append(line[i]);
                                break;
                        }
                        
                        i++;
                    }
                    if (!readNextLine && currentColumn == this.column)
                    {
                        newItem = charStack.ToString();
                        if (trim)
                            newItem = newItem.Trim();
                        if (!string.IsNullOrEmpty(newItem))
                            cachedColumns.Add(newItem);
                    }
                }
            }
        

        }

        #endregion
    }
}
